package com.fxd.util;

import com.fxd.conn.JedisConnUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;

import java.util.Random;

/**
 * 限流工具类
 */
public class CurrentLimitingUtil {

    private CurrentLimitingUtil() {
    }

    /**
     * 简单限流，如果几秒内访问几万次是不适合的，消耗内存过大
     *
     * @param key    键
     * @param during 几秒内
     * @param times  几秒内访问的最大次数
     * @return
     */
    public static boolean simpleCurrentLimiting(String key, Integer during, Integer times) {
        //获取jedis实例
        Jedis jedis = JedisConnUtil.getJedis();
        long curTime = System.currentTimeMillis();
        Pipeline pipelined = jedis.pipelined();
        pipelined.multi();  //开启事务
        //value直接用时间戳，可能由于太快导致value相同而存不进去，这里任然有千分之一的几率value相同，但是用户多访问一次影响不大
        pipelined.zadd(key, curTime, String.valueOf(curTime) + new Random().nextInt(1000));  //value没什么含义，保证唯一就行
        //该方法会包含[min,max]
        pipelined.zremrangeByScore(key, 0, curTime - during * 1000);  //去除掉近during秒之外的值
        Response<Long> zCount = pipelined.zcard(key);  //相当于count()
        pipelined.expire(key, during + 1);  //设置过期时间，多加一秒，防止内存消耗太多
        pipelined.exec();  //结束事务
        pipelined.close();
        return zCount.get() <= times;
    }

}
